from flask import Flask, session, g
from exts import db, mail
import config
from blueprints.qa import bp as qa_bp
from blueprints.auth import bp as auth_bp
from models import UserModel
from flask_migrate import Migrate

from sqlalchemy import text  # 用于sql安全

# 实例化Flask应用，是整个web应用的核心：负责处理请求、路由、配置、扩展等一切功能
app = Flask(__name__)

# 绑定配置文件
app.config.from_object(config)

# 将 db 和 app 正式绑定，加载数据库配置,延迟绑定，不用 db = SQLAlchemy（app）
db.init_app(app)
# 把 mail 这个邮件扩展“初始化”到指定的 Flask 应用 app 上，使其能够读取配置、发送邮件，并支持应用上下文。
mail.init_app(app)

# 绑定 app 和 db	告诉 Flask-Migrate：你要管理的是哪个应用和数据库
migrate = Migrate(app, db)

# 在app中注册蓝图
app.register_blueprint(auth_bp)
app.register_blueprint(qa_bp)


# 作用：用来判断用户是否登录，否则先登录才能做其他操作
# 钩子函数hook,请求处理装饰器,相当于拦截器”或“中间件：before_request,before_first_request,after_request,context_processor
@app.before_request
def my_before_request():
    # 1、从浏览器的session中获取到user_id
    user_id = session.get("user_id")
    # 2、判断用户id是否为空
    if user_id:
        # 3、在数据库表中查找user_id对应的user
        user = UserModel.query.get(user_id)
        # 4、把用户与全局对象global绑定
        setattr(g, "user", user)
    else:
        setattr(g, "user", None)


# 用context_processor把变量user放到上下文管理器中，也就是放到了所有模板当中，任何一个模板被渲染后都可以直接使用变量user，比如每个网页右上角都显示登录的用户名
@app.context_processor
def my_context_processor():
    # 所有模板中都可以使用user
    return {"user": g.user}


if __name__ == "__main__":
    app.run(debug=True, host="0.0.0.0", port=5000)

# # 测试数据库连接是否正常
# # with app.app_context():
# #     with db.engine.connect() as conn:
# #         # text()函数用于sql安全，防止sql注入，支持参数化查询，用 :param 占位符 + 参数传值，绝不拼接用户输入
# #         rs = conn.execute(text("select 1"))
# #         print(rs.fetchone())
